home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / GL / buttonfly / buttonfly.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  30KB  |  1,287 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /* 12/13/91  Modified technique of handling the DO IT selection from the
  19.    pop-up menu to eliminate use of qenter()  (Marvin Kong, 12/13/91).
  20. */
  21.  
  22. /* 4/25/90  Updated to eliminate executing the action twice if the left
  23.    or middle mouse button is double-clicked.  This is done by using TIMER0
  24.    to add events into the queue approximately every 0.5 s, and checking
  25.    the amount of time between mouse clicks.  If within 1 s, the action
  26.    is not performed (Marvin Kong, 4/25/90).
  27. */
  28.  
  29. /* 6/26/89 Updated to provide usability on an eight bitplane Personal IRIS.
  30.    The following constraints are in affect for the P.I.:  1) Only one button
  31.    color is available.  This color is taken from the default color definition
  32.    in the main .menu file.  2) The eight bitplane version destroys the lower 16
  33.    colors of the colormap, so a method was devised to reset the colormap to the
  34.    buttonfly colors when the mouse move into the buttonfly window.  No action
  35.    is taken when the mouse is moved out of the window, however the default
  36.    lower 16 colors are reset when buttonfly is exited.  3) Dithered lighting
  37.    was not used primarily because of degredation in performance due to the
  38.    required Gouraud shading model.
  39.  */
  40. #include <stdio.h>
  41. #include <math.h>
  42. #include <gl/gl.h>
  43. #include <gl/device.h>
  44. #include "event.h"
  45. #include "kurtfont.h"
  46. #include "buttonfly.h"
  47. #include "data.h"
  48.  
  49. #define X 0
  50. #define Y 1
  51. #define Z 2
  52.  
  53. short dev,val;
  54. long originx, originy, sizex, sizey;
  55. long s_originx, s_originy, s_sizex, s_sizey;
  56.  
  57. int flyinflag = 0;
  58. int flyoutflag = 0;
  59. int selectflag = 0;
  60. int exitflag = 0;
  61.  
  62. int tick = 3;        /*  counter for timer events (MKK, 4/25/90) */
  63.  
  64. button_struct *load_buttons(), *which_button();
  65. extern button_struct *new_button(char *);
  66.  
  67. button_struct *current_buttons=NULL, *selected=NULL;
  68.  
  69. path_struct *path=NULL;
  70.  
  71. button_struct *rootbutton;
  72.  
  73. float *curbackcolor;        /* RGBmode current background color */
  74.  
  75. int cm_backcolor[3];        /* color mode background color (unsigned short) */
  76. int eightbit = 0;            /* flag for RGB/colormode */
  77. short *buttonmaparray;        /* array to save colormap indexes */
  78. int have_texture = 0;
  79.  
  80. /* matrix for projecting next set of buttons
  81.    on the back of the selected button */
  82.  
  83. float tv[4][4] = {
  84.  
  85.     {SCREEN, 0.0, 0.0, 0.0},
  86.     {0.0, SCREEN, 0.0, 0.0},
  87.     {0.0, 0.0, SCREEN, -1.0},
  88.     {0.0, 0.0, 0.0, 0.0},
  89. };
  90.  
  91. main (argc, argv)
  92. int    argc;
  93. char    *argv[];
  94. {
  95.     extern char *getcwd();
  96.     void bf_redraw(), bf_exit(int), bf_selecting();
  97.     void bf_quick(), bf_fly(), do_popup(), toggle_window();
  98.     void flyindraw(), flyoutdraw(), selectdraw();
  99.     void parse_args(), doclear();
  100.     void cm_map_button_colors();
  101.     void cm_restore_colormap();
  102.     void cm_save_colormap();
  103.  
  104.     void add_tick();        /* routine to keep time (MKK, 4/25/90)  */
  105.     void doit_bf_fly();        /* routine to flip button (MKK, 12/13/91) */
  106.  
  107.     rootbutton = new_button("");
  108.     rootbutton->cwd = getcwd(NULL, 128);
  109.     selected = rootbutton;
  110.     parse_args(argc, argv);
  111.     selected = NULL;
  112.  
  113.     keepaspect(5, 4);
  114.  
  115.     {
  116.     char *t, *strrchr();
  117.     winopen((t=strrchr(argv[0], '/')) != NULL ? t+1 : argv[0]);
  118.     }
  119.  
  120.     {
  121.     char buf[16];
  122.     gversion(buf);
  123.     have_texture = (strncmp(buf, "GL4DRE",6) == 0);
  124.     }
  125.  
  126.     /* here's where we determine if it's eight bit */
  127.     /* eightbit = (getplanes() < 12); */
  128.     if ((getgdesc(GD_BITS_NORM_DBL_RED)) < 4)
  129.         eightbit = TRUE;
  130.     /* eightbit = TRUE;        /* OMIT! For testing on 24bit only */
  131.  
  132.     getorigin(&originx, &originy);
  133.     getsize(&sizex, &sizey);
  134.     subpixel(TRUE);
  135.     dither(FALSE);
  136.  
  137.     if (eightbit) {
  138.     /* arrays to save color indexed for eight bitplane */
  139.     buttonmaparray = (short *)malloc(3 * 16 * sizeof(short));
  140.  
  141.     doublebuffer();
  142.     gconfig();
  143.     cm_map_button_colors();
  144.     cm_save_colormap(buttonmaparray,0,15);
  145.     } else {
  146.     doublebuffer();
  147.     RGBmode();
  148.     gconfig();
  149.     if (getgdesc(GD_MULTISAMPLE) == 1) {
  150.         zbsize(0);
  151.         mssize(16,32,0);
  152.         gconfig();
  153.         if (getgconfig(GC_MS_SAMPLES) <= 4) {
  154.         zbsize(32);
  155.         mssize(0,0,0);
  156.         gconfig();
  157.         }
  158.     } 
  159.     lmdef(DEFMATERIAL, 1, 0, mat);
  160.     lmdef(DEFLIGHT, 1, 0, light1);
  161.     lmdef(DEFLIGHT, 2, 0, light2);
  162.     lmdef(DEFLMODEL, 1, 0, light_model);
  163.  
  164.     curbackcolor=rootbutton->backcolor;
  165.     }
  166.     shademodel(FLAT);
  167.     backface(TRUE);
  168.  
  169.     qdevice(REDRAW);
  170.     add_event(ANY, REDRAW, ANY, bf_redraw, 0);
  171.  
  172.     qdevice(ESCKEY);
  173.     /*
  174.      * Ill-behaved programs that exit on ESC down can make buttonfly
  175.      * exit accidently with the ESC up event.  bf_exit will look for
  176.      * both a down and an up event before exiting.
  177.      */
  178.     add_event(ANY, ESCKEY, DOWN, bf_exit, (void *)0);
  179.     add_event(ANY, ESCKEY, UP, bf_exit, (void *)1);
  180.  
  181.     qdevice(WINQUIT);
  182.     qdevice(WINSHUT);
  183.     /*
  184.      * The 2 passed to bf_exit means exit immediately.  See discussion
  185.      * of ESCKEY handling above.
  186.      */
  187.     add_event(ANY, WINQUIT, ANY, bf_exit, (void *)2);
  188.  
  189.     qdevice(MIDDLEMOUSE);
  190.     tie(MIDDLEMOUSE, MOUSEX, MOUSEY);
  191.     add_event(ANY, MIDDLEMOUSE, DOWN, bf_selecting, 0);
  192.     add_event(ANY, MIDDLEMOUSE, UP, bf_quick, 0);
  193.  
  194.     qdevice(LEFTMOUSE);
  195.     tie(LEFTMOUSE, MOUSEX, MOUSEY);
  196.     add_event(ANY, LEFTMOUSE, DOWN, bf_selecting, 0);
  197.     add_event(ANY, LEFTMOUSE, UP, bf_fly, 0);
  198.  
  199.     qdevice(RIGHTMOUSE);
  200.     tie(RIGHTMOUSE, MOUSEX, MOUSEY);
  201.     add_event(ANY, RIGHTMOUSE, DOWN, do_popup, 0);
  202.  
  203.     qdevice(SPACEKEY);
  204.     add_event(ANY, SPACEKEY, UP, toggle_window, 0);
  205.  
  206.     if (eightbit) {
  207.     qdevice(INPUTCHANGE);
  208.         add_event(ANY, INPUTCHANGE, 1, cm_restore_colormap, 0);
  209.     }
  210.  
  211.     add_update(&flyinflag, flyindraw, 0);
  212.     add_update(&flyoutflag, flyoutdraw, 0);
  213.     add_update(&selectflag, selectdraw, 0);
  214.  
  215.     qdevice(TIMER0);                    /* Add  event into   */
  216.     add_event(ANY, TIMER0, ANY, add_tick, 0);        /* queue every 30    */
  217.     noise(TIMER0,30);                    /* TIMER events.     */
  218.  
  219.     mmode(MPROJECTION);
  220.  
  221.     perspective(450, 5.0/4.0, THICK, 9.0);
  222.     translate(0.0, 0.0, -5.0/4.0);
  223.  
  224.     mmode(MVIEWING);
  225.     loadmatrix(idmat);
  226.  
  227.     doclear();
  228.  
  229.     draw_buttons(current_buttons);
  230.     swapbuffers();
  231.  
  232.     while(exitflag == FALSE)
  233.     {
  234.     event();
  235.     }
  236.     gexit();
  237.     exit(0);
  238. }
  239.  
  240.  
  241. void do_action(char * act)
  242. {
  243.     int stat;
  244.  
  245.     stat = fork();
  246.     if (stat != 0)
  247.     {
  248.     if (stat < 0)
  249.         perror("Buttonfly:  Trying to fork");
  250.     return;
  251.     }
  252.  
  253.     system(act);
  254.     exit(0);
  255. }
  256.  
  257.     
  258.  
  259. void parse_args(argc, argv)
  260. int argc;
  261. char **argv;
  262. {
  263.     if (argc > 2) {
  264.     fprintf(stderr, "usage: %s [infile]\n", argv[0]);
  265.     exit(1);
  266.     } else if (argc == 2) {
  267.     FILE *fp;
  268.     if ((fp = fopen(argv[1], "r")) == NULL) {
  269.         fprintf(stderr, "%s: can't open file %s\n",
  270.             argv[0], argv[1]);
  271.         exit(1);
  272.     }
  273.     current_buttons = load_buttons(fp);
  274.     fclose(fp);
  275.     } else {
  276.     FILE *fp;
  277.     if ((fp = fopen(".menu", "r")) == NULL) {
  278.         fprintf(stderr, "%s: can't find default file .menu\n",
  279.             argv[0], argv[1]);
  280.         exit(1);
  281.     }
  282.     current_buttons = load_buttons(fp);
  283.     fclose(fp);
  284.     }
  285. }
  286.  
  287.  
  288. void bf_exit(int flag)
  289. {
  290.     void cm_restore_news_colors(void);
  291.  
  292.     static int armed = 0;
  293.  
  294.     switch(flag)
  295.     {
  296.     case 0:
  297.         armed = 1;    /* ESC down event; can exit if we get ESC UP */
  298.         break;
  299.     case 1:
  300.         if (armed == 0)
  301.         break;
  302.         /* If are armed, will fall through to exit case */
  303.     case 2:
  304.             if (eightbit)
  305.             cm_restore_news_colors();
  306.         exitflag = TRUE;
  307.         break;
  308.     }
  309. }
  310.  
  311.  
  312. void  bf_selecting()
  313. {
  314.     short mx, my;
  315.  
  316.     qread(&mx);
  317.     qread(&my);            /* Yank off queue */
  318.  
  319.     if (flyinflag || flyoutflag) return;
  320.  
  321.     /*selectflag = TRUE;*/        /*  Don't update button if a     */
  322.     if( tick > 2 ) selectflag = TRUE;    /*  double-click (MKK, 4/25/90). */
  323.  
  324.     flyinflag = flyoutflag = FALSE;
  325. }
  326.  
  327.  
  328. /*
  329.  *    Middle mouse up == quick selection, no flipping
  330.  */
  331. void bf_quick()
  332. {
  333.     short mx, my;
  334.  
  335.     qread(&mx);
  336.     qread(&my);            /* Yank off queue */
  337.  
  338.     if (flyinflag || flyoutflag) return;
  339.  
  340.     selectflag = flyinflag = flyoutflag = FALSE;
  341.     selected = which_button(mx, my);
  342.     if (selected) {
  343.     push_button(selected);
  344.     if (selected->forward) {
  345.         add_button_to_path(current_buttons, selected);
  346.         current_buttons = selected->forward;
  347.     }
  348.     else if (path) {
  349.         chdir(path->button->cwd);
  350.     }
  351.     else chdir(rootbutton->cwd);
  352.     selected = NULL;
  353.     } else if (path) {
  354.  
  355.     path_struct    *step;
  356.  
  357.     if( tick < 2 )        /*  This was added to        */
  358.         return;        /*  eliminate double-clicks  */
  359.     else            /*  (MKK, 4/25/90).          */
  360.         tick = 0;
  361.  
  362.     selected = path->button;
  363.     draw_selected_button(selected, 1.0);
  364.     selected = NULL;
  365.     current_buttons = path->current_buttons;
  366.     step = path;
  367.     path = path->back;
  368.     free(step);
  369.  
  370.     if (path) {
  371.         curbackcolor = path->button->backcolor;
  372.         chdir(path->button->cwd);
  373.     } else {
  374.         curbackcolor = rootbutton->backcolor;
  375.         chdir(rootbutton->cwd);
  376.     }
  377.     }
  378.     bf_redraw();
  379. }
  380.  
  381.  
  382. void bf_fly()
  383. {
  384.     short           mx, my;
  385.     qread(&mx);
  386.     qread(&my);            /* Yank off queue */
  387.  
  388.     if (flyinflag || flyoutflag) return;
  389.  
  390.     selectflag = flyinflag = flyoutflag = FALSE;
  391.     selected = which_button(mx, my);
  392.     if (selected) {
  393.     push_button(selected);
  394.     if (selected->forward) {
  395.         add_button_to_path(current_buttons, selected);
  396.         flyinflag = TRUE;
  397.     } else {
  398.         if (path) chdir(path->button->cwd);
  399.         else chdir(rootbutton->cwd);
  400.         selected = NULL;
  401.         bf_redraw();
  402.     }
  403.     } else if (path) {
  404.     path_struct    *step;
  405.  
  406.     if( tick < 2 )        /*  This was added to        */
  407.         return;        /*  eliminate double-clicks  */
  408.     else            /*  (MKK, 4/25/90).          */
  409.         tick = 0;
  410.  
  411.     flyoutflag = TRUE;
  412.     selected = path->button;
  413.     current_buttons = path->current_buttons;
  414.     step = path;
  415.     path = path->back;
  416.     free(step);
  417.  
  418.     if (path) {
  419.         chdir(path->button->cwd);
  420.         curbackcolor = path->button->backcolor;
  421.     }
  422.     else {
  423.         chdir(rootbutton->cwd);
  424.         curbackcolor = rootbutton->backcolor;
  425.     }
  426.     }
  427. }
  428.  
  429.  
  430. void bf_redraw()
  431. {
  432.     reshapeviewport();
  433.     getorigin(&originx, &originy);
  434.     getsize(&sizex, &sizey);
  435.     doclear();
  436.     draw_buttons(current_buttons);
  437.     swapbuffers();
  438. }
  439.  
  440.  
  441. #define BIG    0
  442. #define LITTLE    1
  443. void  toggle_window()
  444. {
  445.     static int      size = LITTLE;
  446.  
  447.     if (size == BIG) {
  448.     size = LITTLE;
  449.     winposition(s_originx, s_originx + s_sizex,
  450.             s_originy, s_originy + s_sizey);
  451.     reshapeviewport();
  452.     keepaspect(getgdesc(GD_XPMAX), getgdesc(GD_YPMAX));
  453.     winconstraints();
  454.     getorigin(&originx, &originy);
  455.     getsize(&sizex, &sizey);
  456.     } else {
  457.     size = BIG;
  458.     getorigin(&s_originx, &s_originy);
  459.     getsize(&s_sizex, &s_sizey);
  460.     winposition(0, getgdesc(GD_XPMAX) - 1, 0, getgdesc(GD_YPMAX) - 1);
  461.     reshapeviewport();
  462.     originx = 0;
  463.     originy = 0;
  464.     sizex = getgdesc(GD_XPMAX);
  465.     sizey = getgdesc(GD_YPMAX);
  466.     }
  467. }
  468.  
  469.  
  470. void  do_popup()
  471. {
  472.     short           mx, my;
  473.     button_struct  *b;
  474.     void            do_buttons_menu();
  475.  
  476.     qread(&mx);
  477.     qread(&my);
  478.     b = which_button(mx, my);
  479.     if (b) {
  480.     do_buttons_menu(b, mx, my);
  481.     } else if (path) {
  482.     do_buttons_menu(path->button, mx, my);
  483.     } else if (rootbutton->popup) {
  484.     do_buttons_menu(rootbutton, mx, my);
  485.     }
  486. }
  487.  
  488.  
  489. void do_buttons_menu(b, mx, my)
  490. button_struct *b;
  491. short mx, my;
  492. {
  493.     long            menu;
  494.     int             i, num;
  495.     char            t[128];
  496.     popup_struct   *scan;
  497.  
  498.     menu = newpup();
  499.  
  500.     if (b != rootbutton) {
  501.     sprintf(t, "Do It", i);
  502.     addtopup(menu, t);
  503.     }
  504.     for (num = 0, scan = b->popup; scan != NULL; num++, scan = scan->next) {
  505.  
  506.     sprintf(t, "%s%%x%d", scan->title, num + 2);
  507.     addtopup(menu, t);
  508.     }
  509.  
  510.     i = dopup(menu);
  511.     freepup(menu);
  512.  
  513.     if (i == 1) {        /* Execute button */
  514.  
  515.     /* DO IT selected from menu (MKK, 12/13/91) */
  516.     doit_bf_fly();
  517.  
  518.     } else if ((i > 1) && (i <= num + 1)) {
  519.  
  520.     for (num = 0, scan = b->popup; num != (i - 2);
  521.          num++, scan = scan->next);    /* Keep on scanning... */
  522.     do_action(scan->action);
  523.     }
  524. }
  525.  
  526.  
  527. void selectdraw()
  528. {
  529.     doclear();
  530.     draw_buttons(current_buttons);
  531.     draw_highlighted_button(which_button(
  532.                    getvaluator(MOUSEX), getvaluator(MOUSEY)));
  533.     swapbuffers();
  534. }
  535.  
  536.  
  537. void flyindraw()
  538. {
  539.     static float    t = 1.0;
  540.     t -= 0.02;
  541.     if (t <= 0.0) {
  542.     current_buttons = selected->forward;
  543.     selected = NULL;
  544.     flyinflag = 0;
  545.     t = 1.0;
  546.  
  547.     curbackcolor = path->button->backcolor;
  548.  
  549.     doclear();
  550.     draw_buttons(current_buttons);
  551.     } else {
  552.     doclear();
  553.     draw_buttons(current_buttons);
  554.     draw_selected_button(selected, t);
  555.     }
  556.     swapbuffers();
  557. }
  558.  
  559.  
  560. void flyoutdraw()
  561. {
  562.     static float    t = 0.0;
  563.  
  564.     doclear();
  565.  
  566.     t += 0.02;
  567.     if (t >= 1.0) {
  568.     t = 0.0;
  569.     selected = NULL;
  570.     flyoutflag = 0;
  571.     draw_buttons(current_buttons);
  572.     } else {
  573.     draw_buttons(current_buttons);
  574.     draw_selected_button(selected, t);
  575.     }
  576.     swapbuffers();
  577. }
  578.  
  579.  
  580. /*
  581.  *    This is called to do whatever action is required when a button is
  582.  * pushed.  It just mucks with the button given to it.
  583.  */
  584. push_button(selected)
  585. button_struct *selected;
  586. {
  587.     int needpipe;
  588.     FILE *fp;
  589.     extern char *getcwd();
  590.  
  591.     if( tick < 2 )         /*  This was added to        */
  592.     return;            /*  eliminate double-clicks  */
  593.     else            /*  (MKK, 4/25/90).          */
  594.     tick = 0;
  595.  
  596.     /* First, go into proper directory */
  597.     /* (execute .cd. command) */
  598.     if (selected->cwd != NULL) {
  599.     if (chdir(selected->cwd) != 0)
  600.     {
  601.         fprintf(stderr, "Buttonfly: problem with .cd. %s",
  602.         selected->cwd);
  603.         perror("");
  604.     }
  605.     free(selected->cwd);
  606.     }
  607.     selected->cwd = getcwd(NULL, 128);
  608.  
  609.     /* Need to open a pipe if submenu == "-" */
  610.     if ((selected->submenu != NULL) &&
  611.     (strcmp(selected->submenu, "-") == 0))
  612.     needpipe = 1;
  613.     else
  614.     needpipe = 0;
  615.  
  616.     /* First, figure out where we'll build submenus from */
  617.     fp = NULL;
  618.     if ((selected->action != NULL) && needpipe) {
  619.     /* This performs the action, saving output */
  620.     fp = popen(selected->action, "r");
  621.     } else if (selected->submenu != NULL) {
  622.     fp = fopen(selected->submenu, "r");
  623.     }
  624.     /* Now, do action */
  625.     if ((selected->action != NULL) && !needpipe) {
  626.     do_action(selected->action);
  627.     }
  628.     /* Ok, now build submenus if we can */
  629.     if (fp != NULL) {
  630.     selected->forward = load_buttons(fp);
  631.     if (needpipe)
  632.         pclose(fp);
  633.     else
  634.         fclose(fp);
  635.     }
  636. }
  637.  
  638. draw_buttons(buttons)
  639. button_struct *buttons;
  640. {
  641.     if (!eightbit) {
  642.     lmbind(LIGHT1, 1);
  643.     lmbind(MATERIAL, 1);
  644.     }
  645.     /* lmbind(LIGHT2, 2); */
  646.  
  647.     if (buttons)
  648.     do {
  649.         if (buttons != selected)
  650.         draw_button(buttons);
  651.     } while (buttons = buttons->next);
  652. }
  653.  
  654.  
  655. draw_button(button)
  656. button_struct *button;
  657. {
  658.     float           r = 1.0, g = 1.0, b = 1.0;
  659.     pushmatrix();
  660.  
  661.     if (!eightbit) {
  662.     tmp_mat[1] = tmp_mat[5] = button->color[0];
  663.     tmp_mat[2] = tmp_mat[6] = button->color[1];
  664.     tmp_mat[3] = tmp_mat[7] = button->color[2];
  665.     lmdef(DEFMATERIAL, 1, 0, tmp_mat);
  666.     }
  667.  
  668.     translate(button->tx, button->ty, button->tz);
  669.  
  670.     rotate(button->ax, 'x');
  671.     /* rotate(button->ay, 'y'); */
  672.     rotate(button->az, 'z');
  673.  
  674.     draw_edge();
  675.  
  676.     draw_front(button);
  677.  
  678.     popmatrix();
  679. }
  680.  
  681.  
  682. draw_highlighted_button(button)
  683. button_struct *button;
  684. {
  685.     if (button) {
  686.  
  687.     if (!eightbit) {
  688.         tmp_mat[1] = tmp_mat[5] = button->highcolor[0];
  689.         tmp_mat[2] = tmp_mat[6] = button->highcolor[1];
  690.         tmp_mat[3] = tmp_mat[7] = button->highcolor[2];
  691.         lmdef(DEFMATERIAL, 1, 0, tmp_mat);
  692.     }
  693.  
  694.     pushmatrix();
  695.  
  696.     translate(button->tx, button->ty, button->tz);
  697.  
  698.     rotate(button->ax, 'x');
  699.     rotate(button->az, 'z');
  700.  
  701.     draw_edge();
  702.     draw_front(button);
  703.  
  704.     popmatrix();
  705.     }
  706. }
  707.  
  708.  
  709. draw_selected_button(button, t)
  710. button_struct *button;
  711. float t;
  712. {
  713.     float           gls, glc;
  714.     Angle           ax, ay, az;
  715.     float           tx, ty, tz;
  716.     int             bc[3], i;
  717.  
  718.     pushmatrix();
  719.  
  720.     ax = (Angle) ((float) button->ax * t);
  721.     /* ay = (Angle)((float)button->ay*t); */
  722.     az = (Angle) ((float) button->az * t);
  723.  
  724.     tx = t * button->tx;
  725.     ty = t * button->ty;
  726.     tz = t * button->tz;
  727.  
  728.     translate(tx, ty, tz);
  729.  
  730.     rotate(ax, 'x');
  731.     /* rotate(ay, 'y'); */
  732.     rotate(az, 'z');
  733.  
  734.     if (!eightbit) {
  735.     if (flyinflag) {    /* current high or current normal button colors */
  736.         tmp_mat[1] = tmp_mat[5] = button->highcolor[0];
  737.         tmp_mat[2] = tmp_mat[6] = button->highcolor[1];
  738.         tmp_mat[3] = tmp_mat[7] = button->highcolor[2];
  739.     } else {
  740.         tmp_mat[1] = tmp_mat[5] = button->color[0];
  741.         tmp_mat[2] = tmp_mat[6] = button->color[1];
  742.         tmp_mat[3] = tmp_mat[7] = button->color[2];
  743.     }
  744.     lmdef(DEFMATERIAL, 1, 0, tmp_mat);
  745.     }
  746.  
  747.     draw_edge();
  748.  
  749.     gl_sincos(ax - 900, &gls, &glc);
  750.  
  751.     if (gls < glc * ty / (-tz + SCREEN + THICK)) {
  752.  
  753.     /* draw back of button */
  754.  
  755.     pushmatrix();
  756.  
  757.     if (eightbit) {
  758.  
  759.         int cm_cindex;
  760.         static int cm_toggle = 0;
  761.  
  762.         /* toggle 2 indices for smooth gradation of button back */
  763.         cm_toggle = 1 - cm_toggle;
  764.         cm_cindex = CM_BUTTONBACKINDEX + cm_toggle;
  765.  
  766.         /* set and map the color. note: bc already multiplied by 255 */
  767.         for (i = 0; i < 3; i++)
  768.         bc[i] = (int) (t * 255.0 + (1.0 - t) * cm_backcolor[i]);
  769.  
  770.         /* to restore colors on inputchange. not REALLY needed now */
  771. /*        *(buttonmaparray + (cm_cindex * 3)) = bc[0];
  772. /*        *(buttonmaparray + (cm_cindex * 3 + 1)) = bc[1];
  773. /*        *(buttonmaparray + (cm_cindex * 3 + 2)) = bc[2];
  774. */
  775.         mapcolor(cm_cindex, (short) bc[0], (short) bc[1], (short) bc[2]);
  776.         color(cm_cindex);
  777.  
  778.     } else {
  779.  
  780.         for (i = 0; i < 3; i++)
  781.         bc[i] = (int)(t*255.0 + (1.0-t)*selected->backcolor[i]*255.0);
  782.  
  783.         RGBcolor(bc[0], bc[1], bc[2]);
  784.  
  785.     }
  786.  
  787.     bgnpolygon();
  788.     v3f(back_polys[0][0]);
  789.     v3f(back_polys[0][1]);
  790.     v3f(back_polys[0][2]);
  791.     v3f(back_polys[0][3]);
  792.     endpolygon();
  793.  
  794.     translate(0.0, 0.0, THICK);
  795.  
  796.     translate(0.0, 0.0, SCREEN);
  797.     multmatrix(tv);
  798.     translate(0.0, 0.0, -SCREEN - THICK);
  799.  
  800.     draw_buttons(button->forward);
  801.  
  802.     popmatrix();
  803.  
  804.     } else {
  805.  
  806.     draw_front(button);
  807.     }
  808.  
  809.     popmatrix();
  810.  
  811. }
  812.  
  813.  
  814. button_struct *load_buttons(fp)
  815. FILE *fp;
  816. {
  817.     button_struct  *scan;
  818.     int             nb, i;
  819.     extern FILE    *lex_fp;
  820.     extern button_struct *buttons_input;
  821.  
  822.     lex_fp = fp;
  823.     yyparse();
  824.  
  825.     nb = 0;            /* Figure out how many buttons were made */
  826.     for (scan = buttons_input; scan != NULL; scan = scan->next)
  827.     ++nb;
  828.  
  829.     if (nb > MAX_SPOTS) {
  830.     fprintf(stderr,
  831.         "Buttonfly Warning: %d is too many buttons\n", nb);
  832.     fprintf(stderr, "(Maximum number is %d)\n", MAX_SPOTS);
  833.     return NULL;
  834.     }
  835.     i = 0;            /* And now figure out where to put them */
  836.     for (scan = buttons_input; scan != NULL; scan = scan->next) {
  837.     scan->tx = spots[nb - 1][i + 0];
  838.     scan->ty = spots[nb - 1][i + 1];
  839.     scan->tz = spots[nb - 1][i + 2];
  840.     i += 3;
  841.     scan->ax = (int) (random(1.0) + 0.5) * 3600 - 1800;
  842.     scan->ay = 0;
  843.     scan->az = (int) (random(1.0) + 0.5) * 3600 - 1800;
  844.     }
  845.     return buttons_input;
  846. }
  847.  
  848.  
  849. stroke(str,xoffset,yoffset)
  850. char *str;
  851. float xoffset,yoffset;
  852. {
  853.     register int i, mode;
  854.  
  855.     pushmatrix();
  856.     translate(xoffset,yoffset,0.0);
  857.     for (; *str; str++) {
  858.     if (chrtbl[*str][0][0]) {
  859.         for (i=0; mode = chrtbl[*str][i][0]; i++) {
  860.         switch (mode) {
  861.         case 1:
  862.             translate((float)chrtbl[*str][i][1], (float)chrtbl[*str][i][2], 0.0);
  863.             break;
  864.         case 2:
  865.             bgnline();
  866.             v2i(&chrtbl[*str][i][1]);
  867.             break;
  868.         case 3:
  869.             v2i(&chrtbl[*str][i][1]);
  870.             break;
  871.         case 4:
  872.             v2i(&chrtbl[*str][i][1]);
  873.             endline();
  874.             break;
  875.         }
  876.         }
  877.     }
  878.     }
  879.     popmatrix();
  880. }
  881.  
  882.  
  883. draw_button_label(button)
  884. button_struct *button;
  885. {
  886.  
  887.     if (eightbit) {
  888.     color(CM_TEXTINDEX);
  889.     } else {
  890.     RGBcolor(200, 200, 200);
  891.     }
  892.  
  893.     scale(-0.015, 0.015, 0.015);
  894.  
  895.     linewidth(sizex * 3 / 1000 + 1);
  896.  
  897.     switch (button->wc) {
  898.  
  899.     case 1:
  900.     stroke(button->name[0],
  901.         -6.0 * strlen(button->name[0]) / 2.0, -4.0, 0.0);
  902.     break;
  903.  
  904.     case 2:
  905.     stroke(button->name[0],
  906.         -6.0 * strlen(button->name[0]) / 2.0, 1.0, 0.0);
  907.     stroke(button->name[1],
  908.         -6.0 * strlen(button->name[1]) / 2.0, -9.0, 0.0);
  909.     break;
  910.  
  911.     case 3:
  912.     stroke(button->name[0],
  913.         -6.0 * strlen(button->name[0]) / 2.0, 6.0, 0.0);
  914.     stroke(button->name[1],
  915.         -6.0 * strlen(button->name[1]) / 2.0, -4.0, 0.0);
  916.     stroke(button->name[2],
  917.         -6.0 * strlen(button->name[2]) / 2.0, -14.0, 0.0);
  918.     break;
  919.     }
  920.     linewidth(1);
  921. }
  922.  
  923. draw_button_label_tex(button)
  924. button_struct *button;
  925. {
  926.  
  927.     float texfntwidth(char *);
  928.     static int once;
  929.  
  930.     if (!once) {
  931.     static char *tfnt = "/usr/demos/data/images/Times-Italic.bw";
  932.     char *p, getenv(char *);
  933.     if (texfntinit((p = getenv("BUTTONFLY_FONT")) ? p : tfnt)< 0) {
  934.         have_texture = 0;
  935.         draw_button_label(button);
  936.         return;
  937.     }
  938.     once = 1;
  939.     }
  940.  
  941.     if (eightbit) {
  942.     color(CM_TEXTINDEX);
  943.     } else {
  944.     RGBcolor(200, 200, 200);
  945.     }
  946.  
  947.     scale(-0.015, 0.015, 0.015);
  948.  
  949.     switch (button->wc) {
  950.  
  951.     case 1:
  952.     texfntstroke(button->name[0],
  953.         -6.0 * texfntwidth(button->name[0]) / 2.0, -4.0, 0.0);
  954.     break;
  955.  
  956.     case 2:
  957.     texfntstroke(button->name[0],
  958.         -6.0 * texfntwidth(button->name[0]) / 2.0, 1.5, 0.0);
  959.     texfntstroke(button->name[1],
  960.         -6.0 * texfntwidth(button->name[1]) / 2.0, -9.5, 0.0);
  961.     break;
  962.  
  963.     case 3:
  964.     texfntstroke(button->name[0],
  965.         -6.0 * texfntwidth(button->name[0]) / 2.0, 6.5, 0.0);
  966.     texfntstroke(button->name[1],
  967.         -6.0 * texfntwidth(button->name[1]) / 2.0, -4.0, 0.0);
  968.     texfntstroke(button->name[2],
  969.         -6.0 * texfntwidth(button->name[2]) / 2.0, -14.5, 0.0);
  970.     break;
  971.     }
  972. }
  973.  
  974.  
  975. button_struct *which_button(mx, my)
  976. int mx, my;
  977. {
  978.     float           x, y;
  979.     button_struct  *button;
  980.  
  981.     button = current_buttons;
  982.  
  983.     if (button)
  984.     do {
  985.  
  986.         x = (float) (mx - sizex / 2 - originx) / (float) sizex;
  987.         y = (float) (my - sizey / 2 - originy) / (float) sizey / 1.25;
  988.  
  989.         x = x * (-button->tz + SCREEN + THICK * 2.0);
  990.         y = y * (-button->tz + SCREEN + THICK * 2.0);
  991.  
  992.         if (button->tx - 0.625 < x && button->tx + 0.625 > x &&
  993.         button->ty - 0.5 < y && button->ty + 0.5 > y) {
  994.  
  995.         return (button);
  996.         }
  997.     } while (button = button->next);
  998.  
  999.     return (NULL);
  1000. }
  1001.  
  1002.  
  1003. add_button_to_path(current, button)
  1004. button_struct *current;
  1005. button_struct *button;
  1006. {
  1007.     path_struct    *step;
  1008.  
  1009.     step = (path_struct *) malloc(sizeof(path_struct));
  1010.  
  1011.     step->current_buttons = current;
  1012.     step->button = button;
  1013.     step->back = path;
  1014.     path = step;
  1015. }
  1016.  
  1017.  
  1018. draw_edge()
  1019. {
  1020.  
  1021.     int             i;
  1022.  
  1023.     if (!eightbit) 
  1024.     lmbind(LMODEL, 1);
  1025.     
  1026.  
  1027.     for (i = 0; i < 8; i++) {
  1028.  
  1029.     if (eightbit)
  1030.         color(cm_buttoncolor[i]);
  1031.  
  1032.     bgnpolygon();
  1033.     n3f(edge_normals[i]);
  1034.     v3f(edge_polys[i][0]);
  1035.     v3f(edge_polys[i][1]);
  1036.     v3f(edge_polys[i][2]);
  1037.     v3f(edge_polys[i][3]);
  1038.     endpolygon();
  1039.     }
  1040.  
  1041.     if (!eightbit)
  1042.     lmbind(LMODEL, 0);
  1043. }
  1044.  
  1045.  
  1046. draw_front(button)
  1047. button_struct *button;
  1048. {
  1049.     if (eightbit)
  1050.     color(CM_BUTTONFRONT);
  1051.     else
  1052.     lmbind(LMODEL, 1);
  1053.  
  1054.     bgnpolygon();
  1055.     n3f(front_normals[0]);
  1056.     v3f(front_polys[0][0]);
  1057.     v3f(front_polys[0][1]);
  1058.     v3f(front_polys[0][2]);
  1059.     v3f(front_polys[0][3]);
  1060.     endpolygon();
  1061.  
  1062.     if (!eightbit)
  1063.     lmbind(LMODEL, 0);
  1064.  
  1065.     translate(0.0, 0.0, -THICK);
  1066.  
  1067.     if (have_texture)
  1068.     draw_button_label_tex(button);
  1069.     else
  1070.     draw_button_label(button);
  1071. }
  1072.  
  1073.  
  1074. void doclear()
  1075. {
  1076.     if(eightbit)
  1077.     color(CM_BACKINDEX);
  1078.     else
  1079.     c3f(curbackcolor);
  1080.     clear();
  1081. }
  1082.     
  1083. /* ------- additional routines code for eight bitplane system ------ */
  1084.  
  1085. /* cm_map_button_colors sets up the color map for colorindex lighting of
  1086.    buttons.  Button material coefficients are extracted from the default
  1087.    definition in .menu (rootbutton->defaults) and the default values in mat.
  1088.    Lighting coefficients are extracted from the RGB definitions in light1,
  1089.    light2, and light_model.  See GT Graphics User's guide for a very poor
  1090.    explanation on how to set up color ramp for lighting.  See data.h for index
  1091.    defines.  Six indexes were used for normal button color and 6 for
  1092.    highlighted button color.  One index for background, two indexes for the
  1093.    back of the button (to toggle for doublebuffer()) and one for the text
  1094.    color.  Eight bitplane system should dither between lighting indexes by
  1095.    default. 
  1096. */ 
  1097. void cm_map_button_colors()
  1098. {
  1099.     void cm_ramp();
  1100.  
  1101.     float           Cme[3], *Csa, *Cma, *Cla, *Cl, *Cmd, *Cms;
  1102.     float           diffuse[3], ambient[3], specular[3];
  1103.     int             i;
  1104.  
  1105.     Cme[0] = Cme[1] = Cme[2] = 0.0;        /* material->EMISSION */
  1106.     Csa = &light_model[1];            /* light_model->AMBIENT */
  1107.     Cma = &rootbutton->default_color[0];    /* material->AMBIENT */
  1108.     Cla = &light1[1];                /* light->AMBIENT */
  1109.     Cl = &light1[5];                /* light->LCOLOR */
  1110.     Cmd = &rootbutton->default_color[0];    /* material->DIFFUSE */
  1111.     Cms = &mat[9];                /* material->SPECULAR */
  1112.  
  1113.     for (i = 0; i < 3; i++) {
  1114.     ambient[i] = Cme[i] + *(Csa+i) * *(Cma+i) + *(Cla+i) * *(Cma+i);
  1115.     diffuse[i] = ambient[i] + *(Cl+i) * *(Cmd+i);
  1116.     specular[i] = diffuse[i] + *(Cl+i) * *(Cms+i);
  1117.     if (ambient[i] > 1.0)
  1118.         ambient[i] = 1.0;
  1119.     if (diffuse[i] > 1.0)
  1120.         diffuse[i] = 1.0;
  1121.     if (specular[i] > 1.0)
  1122.         specular[i] = 1.0;
  1123.     }
  1124.  
  1125.     /* map the colors ramps */
  1126.     cm_ramp(CM_BUTTONINDEX, CM_BUTTONINDEX+CM_DIFFUSEOFFSET, ambient, diffuse);
  1127.     cm_ramp(CM_BUTTONINDEX+CM_DIFFUSEOFFSET, CM_BUTTONINDEX+CM_SPECULAROFFSET,
  1128.         diffuse, specular);
  1129.  
  1130.     cm_backcolor[0] = (int) (rootbutton->backcolor[0] * 255.0 + 0.5),
  1131.     cm_backcolor[1] = (int) (rootbutton->backcolor[1] * 255.0 + 0.5),
  1132.     cm_backcolor[2] = (int) (rootbutton->backcolor[2] * 255.0 + 0.5);
  1133.     mapcolor(CM_BACKINDEX, cm_backcolor[0], cm_backcolor[1], cm_backcolor[2]);
  1134.  
  1135.     mapcolor(CM_BUTTONBACKINDEX, cm_backcolor[0], cm_backcolor[1],
  1136.          cm_backcolor[2]);
  1137.     mapcolor(CM_BUTTONBACKINDEX + 1, cm_backcolor[0], cm_backcolor[1],
  1138.          cm_backcolor[2]);
  1139.  
  1140.     mapcolor(CM_TEXTINDEX, 200, 200, 200);
  1141. }
  1142.  
  1143. /* cm_ramp builds a linear ramp between two colors within the colorindexes
  1144.    given.
  1145. */
  1146. void cm_ramp(lowindex, highindex, lowcolor, highcolor)
  1147. int lowindex, highindex;
  1148. float *lowcolor, *highcolor;
  1149. {
  1150.     float           r, g, b;
  1151.     float           rinc, binc, ginc;
  1152.     int             i;
  1153.  
  1154.     if (highindex - lowindex == 0)
  1155.     return;
  1156.  
  1157.     r = *lowcolor;
  1158.     g = *(lowcolor + 1);
  1159.     b = *(lowcolor + 2);
  1160.  
  1161.     rinc = (*highcolor - r) / (highindex - lowindex);
  1162.     ginc = (*(highcolor + 1) - g) / (highindex - lowindex);
  1163.     binc = (*(highcolor + 2) - b) / (highindex - lowindex);
  1164.  
  1165.     for (i = lowindex; i < highindex; i++) {
  1166.     mapcolor(i,(short)(r*255.0+0.5),(short)(g*255.0+0.5),
  1167.          (short)(b*255.0+0.5));
  1168.     r += rinc;
  1169.     g += ginc;
  1170.     b += binc;
  1171.     }
  1172. }
  1173.  
  1174. /* This routine saves the color map entries from c1 to c2 in an array
  1175. called savearray.  Savearray must be 3 time the number of color entries
  1176. to be saved times the the size os a short (3 * (c2 - c1) *
  1177. sizeof(short)).  
  1178. */
  1179. void cm_save_colormap(savearray,c1,c2)
  1180. short *savearray;
  1181. Colorindex c1, c2;
  1182. {
  1183.     Colorindex      i;
  1184.     int             n;
  1185.  
  1186.     for (i = c1, n = 0; i <= c2; i++, n += 3) {
  1187.     getmcolor(i, &savearray[n], &savearray[n + 1], &savearray[n + 2]);
  1188.     }
  1189. }
  1190.  
  1191. /* This routine restores the color map entries c1 through c2 from
  1192. entries that have been stored in savearray.  Restore_colormap is
  1193. intended to compliment save_colormap.  
  1194. */
  1195. /* void cm_restore_colormap(savearray,c1,c2) */
  1196. void cm_restore_colormap()
  1197. {
  1198.     short *savearray = &buttonmaparray[0];
  1199.     Colorindex c1 = 0, c2 = 15;
  1200.         Colorindex      i;
  1201.         int             n;
  1202.  
  1203.     for (i = c1, n = 0; i <= c2; i++, n += 3) {
  1204.     mapcolor(i, savearray[n], savearray[n + 1], savearray[n + 2]);
  1205.     }
  1206. }
  1207.  
  1208. /* Restore news colors on exit */
  1209. void cm_restore_news_colors()
  1210. {
  1211.     mapcolor(0, 0, 0, 0);
  1212.     mapcolor(1, 255, 0, 0);
  1213.     mapcolor(2, 0, 255, 0);
  1214.     mapcolor(3, 255, 255, 0);
  1215.     mapcolor(4, 0, 0, 255);
  1216.     mapcolor(5, 255, 0, 255);
  1217.     mapcolor(6, 0, 255, 255);
  1218.     mapcolor(7, 255, 255, 255);
  1219.     mapcolor(8, 85, 85, 85);
  1220.     mapcolor(9, 198, 113, 113);
  1221.     mapcolor(10, 113, 198, 113);
  1222.     mapcolor(11, 142, 142, 56);
  1223.     mapcolor(12, 113, 113, 198);
  1224.     mapcolor(13, 142, 56, 142);
  1225.     mapcolor(14, 56, 142, 142);
  1226.     mapcolor(15, 170, 170, 170);
  1227. }
  1228.  
  1229. void add_tick()
  1230. {
  1231.     tick++;            /* Count number of timer events since last */
  1232.     if(tick > 7200) tick = 2;   /* left or middle mouse (MKK, 4/25/90).    */
  1233. }
  1234.  
  1235. void doit_bf_fly()
  1236. {
  1237.     short           mx, my;
  1238.  
  1239.     /*  Flip the current button forward (MKK, 12/13/91). */
  1240.  
  1241.     mx = getvaluator(MOUSEX);
  1242.     my = getvaluator(MOUSEY);
  1243.  
  1244.     if (flyinflag || flyoutflag) return;
  1245.  
  1246.     selectflag = flyinflag = flyoutflag = FALSE;
  1247.     selected = which_button(mx, my);
  1248.     if (selected) {
  1249.     push_button(selected);
  1250.     if (selected->forward) {
  1251.         add_button_to_path(current_buttons, selected);
  1252.         flyinflag = TRUE;
  1253.     } else {
  1254.         if (path) chdir(path->button->cwd);
  1255.         else chdir(rootbutton->cwd);
  1256.         selected = NULL;
  1257.         bf_redraw();
  1258.     }
  1259.     } else if (path) {
  1260.     path_struct    *step;
  1261.  
  1262.     if( tick < 2 )        /*  This was added to        */
  1263.         return;        /*  eliminate double-clicks  */
  1264.     else            /*  (MKK, 4/25/90).          */
  1265.         tick = 0;
  1266.  
  1267.     flyoutflag = TRUE;
  1268.     selected = path->button;
  1269.     current_buttons = path->current_buttons;
  1270.     step = path;
  1271.     path = path->back;
  1272.     free(step);
  1273.  
  1274.     if (path) {
  1275.         chdir(path->button->cwd);
  1276.         curbackcolor = path->button->backcolor;
  1277.     }
  1278.     else {
  1279.         chdir(rootbutton->cwd);
  1280.         curbackcolor = rootbutton->backcolor;
  1281.     }
  1282.     }
  1283. }
  1284.  
  1285. /***** END OF FILE ***** END OF FILE ***** END OF FILE ***** END OF FILE *****/
  1286.  
  1287.